package com.connector.base.connection.impl;

import com.connector.base.connection.Connection;
import com.connector.base.connection.SessionContext;
import com.connector.base.connection.channel.SocketChannel;
import com.connector.base.connection.channel.SocketIoSocketChannel;
import com.connector.base.exception.ConnectorException;
import com.corundumstudio.socketio.protocol.Packet;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SocketIoConnection implements Connection<Packet>
{
    private static final Logger log;
    private static final int DEFAULT_TIMEOUT = 1000;
    private SessionContext context;
    private SocketChannel socketClient;
    private volatile byte status;
    private long lastReadTime;
    private long lastWriteTime;
    private int timeout;
    private String userId;

    public SocketIoConnection() {
        this.status = 0;
        this.timeout = 1000;
    }

    @Override
    public void init(final SocketChannel clientChannel) {
        this.socketClient = clientChannel;
        this.context = new SessionContext();
        this.lastReadTime = System.currentTimeMillis();
        this.status = 1;
    }

    @Override
    public SessionContext getSessionContext() {
        return this.context;
    }

    @Override
    public void setSessionContext(final SessionContext context) {
        this.context = context;
    }

    @Override
    public ChannelFuture channelSend(final Packet packet) {
        throw new ConnectorException("this method do not support for socket io server!");
    }

    @Override
    public ChannelFuture channelSend(final Packet packet, final ChannelFutureListener listener) {
        throw new ConnectorException("this method do not support for socket io server!");
    }

    @Override
    public void sendEvent(final String eventName, final Object... data) {
        final SocketIoSocketChannel socketIoSocketChannel = (SocketIoSocketChannel)this.socketClient;
        socketIoSocketChannel.getSocketIOClient().sendEvent(eventName, data);
    }

    @Override
    public ChannelFuture channelClose() {
        throw new ConnectorException("this method do not support for socket io server!");
    }

    @Override
    public void disConnect() {
        final SocketIoSocketChannel socketIoSocketChannel = (SocketIoSocketChannel)this.socketClient;
        socketIoSocketChannel.getSocketIOClient().disconnect();
    }

    @Override
    public String getId() {
        return null;
    }

    @Override
    public boolean isConnected() {
        final SocketIoSocketChannel client = (SocketIoSocketChannel)this.socketClient;
        return client.getSocketIOClient().isChannelOpen();
    }

    @Override
    public boolean isReadTimeout() {
        return System.currentTimeMillis() - this.lastReadTime > this.context.getHeartbeat() + this.timeout;
    }

    @Override
    public boolean isWriteTimeout() {
        return System.currentTimeMillis() - this.lastWriteTime > this.context.getHeartbeat() - this.timeout;
    }

    @Override
    public void updateLastReadTime() {
        this.lastReadTime = System.currentTimeMillis();
    }

    @Override
    public void updateLastWriteTime() {
        this.lastWriteTime = System.currentTimeMillis();
    }

    @Override
    public SocketChannel getSocketClient() {
        return this.socketClient;
    }

    @Override
    public String toString() {
        return "SocketIoConnection(context=" + this.context + ", socketClient=" + this.getSocketClient() + ", status=" + this.status + ", lastReadTime=" + this.lastReadTime + ", lastWriteTime=" + this.lastWriteTime + ", timeout=" + this.timeout + ", userId=" + this.userId + ")";
    }

    static {
        log = LoggerFactory.getLogger((Class) SocketIoConnection.class);
    }
}
